/*
 * callbacks.c
 * Copyright (C) Pietro Pilolli 2010 <pilolli@fbk.eu>
 * 
 * curtain is free software: you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the
 * Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * curtain is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License along
 * with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#ifdef HAVE_CONFIG_H
#  include <config.h>
#endif

#include "callbacks.h"
#include "utils.h"
#include <gdk/gdkkeysyms.h>
#include <math.h>
#include <stdlib.h>

#include <cairo.h>

#ifdef _WIN32
#define CURTAIN_FILE "..\\share\\curtain\\ui\\curtain.png"
#else
#define CURTAIN_FILE PACKAGE_DATA_DIR"/curtain/ui/curtain.png"
#endif 
/* This is for local testing*/
//#define CURTAIN_FILE "curtain.png"


/* main cairo context */
cairo_t *cr;

/* Used to shape input mask */
cairo_t *shape_cr = NULL;
GdkBitmap* shape;

double x=0;
double y=0;

double minx;
double maxx;
double miny;
double maxy;

int screen_width;
int screen_height;

GdkPixbuf *pixbuf = NULL;

gboolean first = TRUE;

void quit()
{
  if (pixbuf)
    {
      g_object_unref(G_OBJECT(pixbuf));
    }
  if (pixbuf)
    {
      g_object_unref(G_OBJECT(shape));
    }
  if (cr)
    {
      cairo_destroy(cr);
    }
  if (shape_cr)
    {
      cairo_destroy(shape_cr);
    }
  gtk_main_quit ();
  exit(1);
}


G_MODULE_EXPORT gboolean 
destroy (GtkWidget *widget, gpointer data)
{
  quit ();
  return TRUE;
}

void paint_cross()
{
  if (cr)
    { 
      int delta = 25;
      char* color = "FFFFFFFF";
      cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
      cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND);
      cairo_set_line_join(cr, CAIRO_LINE_JOIN_ROUND);
      cairo_set_source_color_from_string(cr, color);
      cairo_rectangle(cr,maxx-delta,miny,delta,delta);	
      cairo_move_to(cr,maxx-delta,miny);
      cairo_line_to(cr,maxx,miny+delta);
      cairo_move_to(cr,maxx,miny);
      cairo_line_to(cr,maxx-delta,miny+delta);
      cairo_stroke(cr);
    }
}


void paint_curtain()
{
  if (cr)
    { 
      cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
      gdk_cairo_set_source_pixbuf(cr, pixbuf, 0.0, 0.0);
      cairo_paint(cr);
    }
}

void reset_shape()
{
  if (shape_cr)
    { 
      cairo_set_operator(shape_cr,CAIRO_OPERATOR_SOURCE);
      cairo_set_source_rgba (shape_cr, 1, 1, 1, 1);
      cairo_paint(shape_cr);
    }
}

/* Expose event: this occurs when the windows is exposed */
G_MODULE_EXPORT gboolean 
on_window_expose_event (GtkWidget *widget,
			GdkEventExpose *event,
		 	gpointer user_data)
{
  int is_fullscreen = gdk_window_get_state (widget->window) & GDK_WINDOW_STATE_FULLSCREEN;
  if (is_fullscreen)
    {
      if (first)
	{
	  minx =0;
	  miny=0;
	  screen_width = gdk_screen_width();
	  screen_height = gdk_screen_height();
	  maxx=screen_width;
	  maxy=screen_height;
	  cr = gdk_cairo_create(widget->window);
	  load_png(CURTAIN_FILE, &pixbuf);
	  
	  shape = gdk_pixmap_new (NULL, screen_width, screen_height, 1);
	  shape_cr = gdk_cairo_create(shape);
	  paint_curtain();
	  paint_cross();
	  first = FALSE;
	}
    }
  return TRUE;
}


G_MODULE_EXPORT gboolean 
on_window_destroy_event (GtkWindow *self, GdkEvent *arg0, gpointer user_data)
{
  quit();
  return TRUE;
}


G_MODULE_EXPORT gboolean 
on_window_button_press_event (GtkWindow *window, GdkEventButton *event, gpointer data)
{
  /* only button1 allowed */
  if (!(event->button==1))
    {
      return FALSE;
    }
  if ((event->x>maxx-25)&&(event->y<miny+25))
    {
      quit();
    }
#ifndef _WIN32
  gtk_widget_input_shape_combine_mask(GTK_WIDGET(window), NULL, 0, 0);
#else
  //grab mouse
  grab_pointer(GTK_WIDGET(window), CURTAIN_MOUSE_EVENTS);
#endif
  reset_shape();
  x = event->x;
  y = event->y;
  return TRUE;
}


void paint_transparent_rectangle(double x, double y, double width, double height)
{
  if (cr)
    {
      cairo_set_operator(cr,CAIRO_OPERATOR_SOURCE);
      cairo_set_source_rgba (cr, 0, 0, 0, 0);
      cairo_rectangle(cr, x, y, width, height);
      cairo_fill(cr);
    }	
  if (shape_cr)
    {
      cairo_set_operator(shape_cr,CAIRO_OPERATOR_SOURCE);
      cairo_set_source_rgba (shape_cr, 0, 0, 0, 0);
      cairo_rectangle(shape_cr, x, y, width, height);
      cairo_fill(shape_cr);	
    }	
}


G_MODULE_EXPORT gboolean 
on_window_button_release_event (GtkWindow *window, GdkEventButton *ev, gpointer data)
{
  /* only button1 allowed and ignore null event */
  if ((!(ev->button==1))||(!ev))
    {
      return FALSE;
    }
  #ifndef _WIN32
  paint_curtain();
  #endif
  double delta_x = fabs(x-ev->x);
  double delta_y = fabs(y-ev->y);

  int minwidth = 25;
  int minheight = 25;

  if (delta_y <= delta_x)
    {
      //move on x axis
      if (ev->x>=x)
	{
	  /* Right gesture */
	  if ((x<(maxx+minx)/2)&&(!(ev->x>maxx)))
	    {
	      // sx to the curtain ->|
	      if (ev->x>minx)
		{
		  //move right of delta_x
		  //printf("->|\n");
		  minx = ev->x;
		  if (minx>maxx-minwidth)
		    {
		      minx=maxx-minwidth;
		    }
		  paint_transparent_rectangle(0, 0, minx, screen_height);
		  paint_transparent_rectangle(maxx, 0, screen_width-maxx, screen_height);
		}
	    }
	  else
	    {
	      //dx to the curtain |->
	      if (ev->x>maxx)
		{
		  //printf("|->\n");
		  paint_transparent_rectangle(ev->x,0,screen_width-ev->x, screen_height);
		  maxx = ev->x;
		  if(maxx>screen_width)
		    {
		      maxx=screen_width;
		    }
		  paint_transparent_rectangle(0, 0, minx, screen_height);
		}
	    }
	}
      else
	{
	  /* Left gesture */
	  if ((x>(maxx+minx)/2)&&(!(ev->x<minx)))
	    {
	      // dx to curtain |<-
	      if (ev->x<maxx)
		{
		  //move left
		  //printf("|<-\n");
		  maxx = ev->x;	
		  if(maxx-minx<minwidth)
		    {
		      maxx=minx+minwidth;
		    }
		  paint_transparent_rectangle(maxx,0,screen_width-maxx, screen_height);
		  paint_transparent_rectangle(0, 0, minx, screen_height);
		}
	    }
	  else
	    {
	      // sx to curtain <-| 
	      if (ev->x<minx)
		{
		  //printf(" <-|\n");
		  paint_transparent_rectangle(0, 0, ev->x, screen_height);
		  minx=ev->x;	
		  if (maxx-minx<minwidth)
		    {
		      maxx=minx+minwidth;
		    }
		  paint_transparent_rectangle(maxx, 0, screen_width-maxx, screen_height);
		}
	    }
	}	
      if (miny>0)
	{
	  paint_transparent_rectangle(0, 0, screen_width, miny);
	}
      if (maxy<screen_height)
	{
	  paint_transparent_rectangle(0, maxy, screen_width, screen_height-maxy);
	}
    }
  else
    {
      //move on y axis
      if (ev->y>=y)
	{
	  // down gesture
	  if ((y<(maxy+miny)/2)&&(!(ev->y>maxy)))
	    {
	      if (ev->y>miny)
		{
		  // up half
		  miny = ev->y;
		  if (miny>maxy-minheight)
		    {
		      miny=maxy-minheight;
		    }
		  paint_transparent_rectangle(0, 0, screen_width, miny);
		  paint_transparent_rectangle(0, maxy, screen_width, screen_height-maxy);
		}
	    }
	  else
	    {
	      if (ev->y>maxy)
		{
		  // down half
		  paint_transparent_rectangle(0, ev->y, screen_width, screen_height-ev->y);
		  maxy = ev->y;
		  if (maxy>screen_height)
		    {
		      maxy=screen_height;
		    }
		  paint_transparent_rectangle(0, 0, screen_width, miny);
		}
	    }
	}
      else
	{
	  // up gesture
	  if ((y<(maxy+miny)/2)||(ev->y<miny))
	    {
	      if (ev->y<miny)
		{
		  // up half
		  //printf("down gesture in first half\n");						
		  miny = ev->y;
		  if (miny>maxy-minheight)
		    {
		      miny=maxy-minheight;
		    }
		  paint_transparent_rectangle(0, 0, screen_width, miny);
		  paint_transparent_rectangle(0, maxy, screen_width, screen_height-maxy);
		}
	    }
	  else
	    {
	      if (ev->y<maxy)
		{
		  //down half
		  //printf("down gesture in second half\n");
		  maxy = ev->y;
		  if(maxy-miny<minheight)
		    {
		      maxy=miny+minheight;
		    }
		  paint_transparent_rectangle(0, maxy, screen_width, screen_height-maxy);
		  paint_transparent_rectangle(0, 0, screen_width, miny);
		}
	    }
	}
      if (minx>0)
	{
	  paint_transparent_rectangle(0, 0, minx, screen_height);
	}
      if (maxx<screen_width)
	{
	  paint_transparent_rectangle(maxx, 0, screen_width-maxx, screen_height);
	}

    }
#ifndef _WIN32
  gtk_widget_input_shape_combine_mask(GTK_WIDGET(window), shape, 0, 0);
#else
  gtk_widget_shape_combine_mask(GTK_WIDGET(window), shape, 0, 0);
  //release mouse
  ungrab_pointer(gdk_display_get_default(), GTK_WIDGET(window));
  //grab focus to prevent an other windows
  paint_curtain();
#endif	  
  paint_cross();
  return TRUE;
}


